using System.Drawing;
using System.Globalization;
using System.IO;
using System.Reflection;
using DslCrossModelFramework;

namespace DslCrossModelFramework {
    /// <summary>
    /// Model File implementation for a model file which is contained in an referenced assembly's resources
    /// </summary>
    public class ReferenceModelFile : ModelFile {

        //public ReferenceModelFile(string assemblyLocation, string referencedAssembly, string resourceName, string referencingProject) {
        //    this.referencedAssembly = referencedAssembly;
        //    this.resourceName = resourceName;
        //    this.referencingProject = referencingProject;
        //    this.assemblyLocation = assemblyLocation;
        //}

        /// <summary>
        /// Initializes a new instance of the <see cref="ReferenceModelFile"/> class.
        /// </summary>
        /// <param name="assemblyFullName">Full name of the assembly.</param>
        /// <param name="assemblyLocation">The assembly location.</param>
        /// <param name="assemblyName">Name of the assembly.</param>
        /// <param name="resourceName">Name of the resource.</param>
        /// <param name="referencingProject">The referencing project.</param>
        /// <param name="packageInfo">The package info.</param>
        public ReferenceModelFile(string assemblyFullName, string assemblyLocation, string assemblyName, string resourceName, string referencingProject, DslToolsPackageInfo packageInfo) {
            this.referencedAssembly = assemblyFullName;
            this.resourceName = resourceName;
            this.referencingProject = referencingProject;
            this.assemblyLocation = assemblyLocation;
            this.owningAssembly = assemblyName;
            this.dslPackageId = packageInfo.Guid;
            if (this.resourceName.StartsWith(owningAssembly) && this.resourceName != string.Format("{0}{1}", this.owningAssembly, packageInfo.FileExtension)) {
                this.name = this.resourceName.Substring(this.owningAssembly.Length + 1);
            }
            else {
                this.name = resourceName;
            }
            this.uniqueModelFileReference = GetModelFileUniqueReference(packageInfo);
        }
        
        /// <summary>
        /// Gets the contents of the DSL model file.
        /// </summary>
        /// <returns></returns>
        public override string GetContents() {
            if(ModelFileHelper.AssemblyReferenceHelper == null) {
                using (AssemblyReferenceHelper helper = new AssemblyReferenceHelper()) {
                    return GetContents(helper);
                }
            }
            else {
                return GetContents(ModelFileHelper.AssemblyReferenceHelper);
            }
        }

        private string GetContents(AssemblyReferenceHelper helper) {
            Stream stream = helper.GetManifestResourceStream(assemblyLocation, resourceName);
            StreamReader sr = new StreamReader(stream);
            return sr.ReadToEnd();
        }

        /// <summary>
        /// Gets the referenced assembly.
        /// </summary>
        /// <value>The referenced assembly.</value>
        public string ReferencedAssembly {
            get { return referencedAssembly; }
        }

        /// <summary>
        /// Gets the name of the resource.
        /// </summary>
        /// <value>The name of the resource.</value>
        public string ResourceName {
            get { return resourceName; }
        }
        private readonly string resourceName;

        /// <summary>
        /// Gets the assembly location.
        /// </summary>
        /// <value>The assembly location.</value>
        public string AssemblyLocation {
            get { return assemblyLocation; }
        }
        private readonly string assemblyLocation;

        /// <summary>
        /// Gets the referencing project.
        /// </summary>
        /// <value>The referencing project.</value>
        public string ReferencingProject {
            get { return referencingProject; }
        }

        /// <summary>
        /// Gets the unique model file reference.
        /// </summary>
        /// <value>The unique model file reference.</value>
        public override string UniqueModelFileReference {
            get { return uniqueModelFileReference; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is dirty.
        /// </summary>
        /// <value><c>true</c> if this instance is dirty; otherwise, <c>false</c>.</value>
        public override bool IsDirty {
            get { return false; }
        }

        public override string LocalFilePath {
            get { return string.Empty; }
        }

        private string uniqueModelFileReference;
        private readonly string referencingProject;

        private readonly string referencedAssembly;

        private string GetModelFileUniqueReference(DslToolsPackageInfo packageInfo) {
            return string.Format(CultureInfo.InvariantCulture, "amr://{0}/{1}/{2}", packageInfo.Guid.ToString(), owningAssembly, resourceName);
        }

        /// <summary>
        /// Gets the icon for the container of this model file.
        /// </summary>
        /// <returns></returns>
        public override Image GetContainerIcon() {
            return Image.FromStream(
                GetType().Assembly.GetManifestResourceStream(
                    string.Format("{0}.Resources.component.bmp", GetType().Namespace)));
        }
    }
}